﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RpcGenerator.Lua
{
    class LuaInvokerGenerator
    {
        public static string Generate(Type type, IMessageSerializer serializer, List<MessageDescription> allDescriptions)
        {
            serializer.NewLine("json = require('json');");
            string invokerName = type.Name + "_Invoker";
                        
            List<MessageDescription> requestDescriptions = allDescriptions.Where(description => description.IsRequest == true).ToList();
            GeneraFields(invokerName, serializer, requestDescriptions);

            GenerateBindMethod(invokerName, serializer, requestDescriptions);

            string fileName = type.Name + "Invoker.lua";
            if (fileName[0] == 'I')
                fileName = fileName.Remove(0, 1);
            return fileName;
        }

        private static void GeneraFields(string invokerName, IMessageSerializer serializer, List<MessageDescription> allDescriptions)
        {
            serializer.NewLine();
            serializer.NewLine(invokerName + " = { };");
            allDescriptions.ForEach(md =>
            {
                serializer.NewLine(string.Format("{0}[{1}] = '{2}';",invokerName,md.MessageId,md.Method.Method.Name));    
            });
        }

        private static void GenerateBindMethod(string invokerName, IMessageSerializer serializer, List<MessageDescription> allDescriptions)
        {
            serializer.NewLine();
            serializer.NewLine(string.Format("function {0}.Bind(impl)",invokerName));
            serializer.BeginBlock(string.Empty);
            {
                serializer.NewLine("    return function(messageid,jsonstring)");
                serializer.NewLine(string.Format("                local methodName = {0}[messageid];", invokerName));
                serializer.NewLine("                if( nil ~= methodName ) then");
                serializer.NewLine("                    local arg = json.decode(jsonstring);");
                serializer.NewLine("                    impl[methodName](arg);");
                serializer.NewLine("                else");
                serializer.NewLine("                    print('method not found,messageid = ' .. messageid);");
                serializer.NewLine("                end");
                serializer.NewLine("           end");
            }
            serializer.EndBlock("end");
        }
    }
}
